import { Body, Controller, Get, Param, Post, Patch, Delete, Query, Res, Headers, Ip, UseGuards } from '@nestjs/common';
import { TrackingService } from './tracking.service';
import { TrackingLoggerService } from './tracking-logger.service';
import { CreateWebsiteDto } from './dto/create-website.dto';
import { UpdateWebsiteDto } from './dto/update-website.dto';
import { TrackPageviewDto } from './dto/track-pageview.dto';
import { WebsiteQueryDto } from './dto/website-query.dto';
import { BatchEventsDto } from './dto/batch-events.dto';
import { Response } from 'express';
import { TokenGuard } from '../../common/guards/token.guard';
import { RolesGuard } from '../../common/guards/roles.guard';
import { Roles } from '../../common/decorators/roles.decorator';

@Controller('tracking')
export class TrackingController {
  constructor(
    private readonly trackingService: TrackingService,
    private readonly trackingLogger: TrackingLoggerService,
  ) {}

  // 管理员API - 需要认证和角色
  @Post('websites')
  @UseGuards(TokenGuard, RolesGuard)
  @Roles('admin', 'devops')
  createWebsite(@Body() createWebsiteDto: CreateWebsiteDto) {
    return this.trackingService.createWebsite(createWebsiteDto);
  }

  @Patch('websites/:id')
  @UseGuards(TokenGuard, RolesGuard)
  @Roles('admin', 'devops')
  updateWebsite(@Param('id') id: string, @Body() updateWebsiteDto: UpdateWebsiteDto) {
    return this.trackingService.updateWebsite(+id, updateWebsiteDto);
  }

  @Delete('websites/:id')
  @UseGuards(TokenGuard, RolesGuard)
  @Roles('admin', 'devops')
  deleteWebsite(@Param('id') id: string) {
    return this.trackingService.deleteWebsite(+id);
  }

  @Delete('websites/all')
  @UseGuards(TokenGuard, RolesGuard)
  @Roles('admin', 'devops')
  deleteAllWebsites() {
    return this.trackingService.deleteAllWebsites();
  }

  @Get('websites')
  @UseGuards(TokenGuard, RolesGuard)
  @Roles('admin', 'devops', 'viewer')
  getAllWebsites() {
    return this.trackingService.getAllWebsites();
  }

  @Get('websites/:id')
  @UseGuards(TokenGuard, RolesGuard)
  @Roles('admin', 'devops', 'viewer')
  getWebsiteById(@Param('id') id: string) {
    return this.trackingService.getWebsiteById(+id);
  }

  @Get('websites/:id/summary')
  @UseGuards(TokenGuard, RolesGuard)
  @Roles('admin', 'devops', 'viewer')
  async getWebsiteSummary(
    @Param('id') id: string,
    @Query() query: WebsiteQueryDto
  ) {
    return this.trackingService.getWebsiteSummary(+id, query);
  }

  @Get('websites/:id/stats')
  @UseGuards(TokenGuard, RolesGuard)
  @Roles('admin', 'devops', 'viewer')
  getWebsiteStats(
    @Param('id') id: string,
    @Query() query: WebsiteQueryDto
  ) {
    return this.trackingService.getWebsiteStats(+id, query);
  }

  @Get('websites/:id/embed-code')
  @UseGuards(TokenGuard, RolesGuard)
  @Roles('admin', 'devops', 'viewer')
  getEmbedCode(@Param('id') id: string) {
    return this.trackingService.getEmbedCode(+id);
  }

  // 新增: 获取网站所有访问过的IP列表
  @Get('websites/:id/ips')
  @UseGuards(TokenGuard, RolesGuard)
  @Roles('admin', 'devops', 'viewer')
  getWebsiteIps(@Param('id') id: string) {
    return this.trackingService.getWebsiteIps(+id);
  }

  // 新增: 获取IP访问详情
  @Get('visits/ip/:ip')
  @UseGuards(TokenGuard, RolesGuard)
  @Roles('admin', 'devops', 'viewer')
  getIpVisits(
    @Param('ip') ip: string,
    @Query('websiteId') websiteId?: string,
    @Query('startDate') startDate?: string,
    @Query('endDate') endDate?: string
  ) {
    return this.trackingService.getIpVisits(
      ip, 
      websiteId ? +websiteId : undefined,
      startDate,
      endDate
    );
  }

  // 新增: 获取会话详情
  @Get('visits/session/:sessionId')
  @UseGuards(TokenGuard, RolesGuard)
  @Roles('admin', 'devops', 'viewer')
  getSessionDetails(@Param('sessionId') sessionId: string) {
    return this.trackingService.getSessionDetails(sessionId);
  }

  // 公共API - 不需要认证
  @Post('pageview')
  async trackPageviewPost(
    @Body() trackPageviewDto: TrackPageviewDto, 
    @Ip() ip: string,
    @Headers('user-agent') userAgent: string,
    @Res() res: Response
  ) {
    return this.handlePageview(trackPageviewDto, ip, userAgent, res);
  }

  @Get('pageview')
  async trackPageviewGet(
    @Query() query: any,
    @Ip() ip: string,
    @Headers('user-agent') userAgent: string,
    @Res() res: Response
  ) {
    // 将查询参数转换为DTO格式
    const trackPageviewDto: TrackPageviewDto = {
      trackingId: query.trackingId,
      url: query.url,
      title: query.title,
      referrer: query.referrer,
      sessionId: query.sessionId,
      customData: query.customData ? JSON.parse(query.customData) : {}
    };
    
    return this.handlePageview(trackPageviewDto, ip, userAgent, res);
  }

  private async handlePageview(
    trackPageviewDto: TrackPageviewDto, 
    ip: string, 
    userAgent: string, 
    res: Response
  ) {
    try {
      // 记录页面访问发送日志
      this.trackingLogger.logPageviewSent(
        trackPageviewDto.trackingId,
        trackPageviewDto.url,
        ip,
        userAgent,
        trackPageviewDto.sessionId || 'unknown',
        trackPageviewDto
      );

      const pageview = await this.trackingService.trackPageview(trackPageviewDto, ip, userAgent);
      
      // 返回1x1像素的GIF图片
      res.setHeader('Content-Type', 'image/gif');
      res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
      res.setHeader('Pragma', 'no-cache');
      res.setHeader('Expires', '0');
      
      // 1x1透明GIF的base64编码
      const gifData = Buffer.from('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7', 'base64');
      res.send(gifData);
    } catch (error) {
      // 记录错误日志
      this.trackingLogger.logError(
        trackPageviewDto.trackingId,
        trackPageviewDto.url,
        ip,
        userAgent,
        trackPageviewDto.sessionId || 'unknown',
        'PAGEVIEW_PROCESSING',
        error,
        trackPageviewDto
      );
      
      // 即使出错也返回图片，避免客户端报错
      res.setHeader('Content-Type', 'image/gif');
      const gifData = Buffer.from('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7', 'base64');
      res.send(gifData);
    }
  }

  @Post('script-loaded')
  async trackScriptLoadedPost(
    @Body() trackPageviewDto: TrackPageviewDto, 
    @Ip() ip: string,
    @Headers('user-agent') userAgent: string,
    @Res() res: Response
  ) {
    return this.handleScriptLoaded(trackPageviewDto, ip, userAgent, res);
  }

  @Get('script-loaded')
  async trackScriptLoadedGet(
    @Query() query: any,
    @Ip() ip: string,
    @Headers('user-agent') userAgent: string,
    @Res() res: Response
  ) {
    // 将查询参数转换为DTO格式
    const trackPageviewDto: TrackPageviewDto = {
      trackingId: query.trackingId,
      url: query.url,
      title: query.title,
      referrer: query.referrer,
      sessionId: query.sessionId,
      customData: query.customData ? JSON.parse(query.customData) : {}
    };
    
    return this.handleScriptLoaded(trackPageviewDto, ip, userAgent, res);
  }

  private async handleScriptLoaded(
    trackPageviewDto: TrackPageviewDto, 
    ip: string, 
    userAgent: string, 
    res: Response
  ) {
    try {
      // 记录脚本加载日志
      this.trackingLogger.logScriptLoaded(
        trackPageviewDto.trackingId,
        trackPageviewDto.url,
        ip,
        userAgent,
        trackPageviewDto.sessionId || 'unknown',
        trackPageviewDto
      );

      // 返回1x1像素的GIF图片
      res.setHeader('Content-Type', 'image/gif');
      res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
      res.setHeader('Pragma', 'no-cache');
      res.setHeader('Expires', '0');
      
      const gifData = Buffer.from('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7', 'base64');
      res.send(gifData);
    } catch (error) {
      // 记录错误日志
      this.trackingLogger.logError(
        trackPageviewDto.trackingId,
        trackPageviewDto.url,
        ip,
        userAgent,
        trackPageviewDto.sessionId || 'unknown',
        'SCRIPT_LOADED_PROCESSING',
        error,
        trackPageviewDto
      );
      
      // 即使出错也返回图片
      res.setHeader('Content-Type', 'image/gif');
      const gifData = Buffer.from('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7', 'base64');
      res.send(gifData);
    }
  }

  // 新增: 批量处理事件端点
  @Post('batch')
  async trackBatchEvents(
    @Body() batchEventsDto: BatchEventsDto,
    @Ip() ip: string,
    @Headers('user-agent') userAgent: string,
    @Res() res: Response
  ) {
    try {
      // 记录批量事件处理开始
      this.trackingLogger.logInfo(
        batchEventsDto.trackingId,
        batchEventsDto.url || 'batch-request',
        ip,
        userAgent,
        batchEventsDto.sessionId || 'unknown',
        'BATCH_PROCESSING_START',
        { eventsCount: batchEventsDto.events?.length || 0 }
      );

      // 处理批量事件
      await this.trackingService.processBatchEvents(
        batchEventsDto,
        ip,
        userAgent
      );
      
      // 记录批量事件处理成功
      this.trackingLogger.logInfo(
        batchEventsDto.trackingId,
        batchEventsDto.url || 'batch-request',
        ip,
        userAgent,
        batchEventsDto.sessionId || 'unknown',
        'BATCH_PROCESSING_SUCCESS',
        { eventsCount: batchEventsDto.events?.length || 0 }
      );

      // 返回204状态码（无内容）
      res.status(204).send();
    } catch (error) {
      // 记录错误日志
      this.trackingLogger.logError(
        batchEventsDto.trackingId,
        batchEventsDto.url || 'batch-request',
        ip,
        userAgent,
        batchEventsDto.sessionId || 'unknown',
        'BATCH_PROCESSING_ERROR',
        error,
        { eventsCount: batchEventsDto.events?.length || 0 }
      );
      
      // 返回202状态码（已接受，但处理可能未完成）
      res.status(202).send();
    }
  }

  @Get('script.js')
  getTrackingScript(@Res() res: Response) {
    const script = this.trackingService.getTrackingScript();
    res.setHeader('Content-Type', 'application/javascript');
    res.setHeader('Cache-Control', 'public, max-age=3600'); // 缓存1小时
    res.send(script);
  }

  @Get('logs/stats')
  @UseGuards(TokenGuard, RolesGuard)
  @Roles('admin', 'devops', 'viewer')
  getLogStats() {
    return this.trackingLogger.getTodayStats();
  }

  @Get('logs/business-loop/:trackingId')
  @UseGuards(TokenGuard, RolesGuard)
  @Roles('admin', 'devops', 'viewer')
  getBusinessLoopLogs(
    @Param('trackingId') trackingId: string,
    @Query('date') date?: string
  ) {
    return this.trackingLogger.getBusinessLoopByTrackingId(trackingId, date);
  }

  @Get('logs/business-loop/:trackingId/integrity')
  @UseGuards(TokenGuard, RolesGuard)
  @Roles('admin', 'devops', 'viewer')
  checkBusinessLoopIntegrity(
    @Param('trackingId') trackingId: string,
    @Query('date') date?: string
  ) {
    return this.trackingLogger.checkBusinessLoopIntegrity(trackingId, date);
  }
} 